package com.lightsh.tabhost;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import android.view.animation.Transformation;
import android.view.animation.TranslateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;

/**
 * Tab的水平/竖直按钮栏(暂时只支持水平)
 * 该类的方法应该只有{@link MyTabHost}访问
 * @author lightsh
 */
public class MyTabWidget extends LinearLayout{
	private static final boolean DEBUG = true;
	private static final String TAG = "MyTabWidget";
	private int mLayoutWidth = -1;
	private int mTabWidth = -1;
	private int mTabCount = 0;
	private int mCurrentTabIndex = 0;
	Context mContext;
	private ImageView mBackgroundView;
	
	// 进行上一状态的记录
	private float mAnimationInterpolatedTime = 1.0f;
	private Animation mTranslateAnimation;
	private Animation mAlphaAnimation1;
	private Animation mAlphaAnimation2;
	
	private Thread mThreadInvalidate;
	
	/**
	 * 动画的持续时间
	 */
	private static final int ANIMATION_TIME = 800;
	private static final float ALPHA_VALUE = 0.5f;
	private static final boolean B_USE_ALPHA = true;
	public MyTabWidget(Context context) {
		this(context, null);
	}
	public MyTabWidget(Context context, AttributeSet attrs) {
		super(context, attrs);
		mContext = context;
		init();
	}
	private void init(){
		setFocusable(true);
	}
	
	
	
	View getChildTabViewAt(int tabIndex){
		return getChildAt(tabIndex);
	}
	
	int getTabCount(){
		return mTabCount;
	}
	int getCurrentTab(){
		return mCurrentTabIndex;
	}
	
	
	void setCurrentTab(int tabIndex){
		if(tabIndex < 0 || tabIndex > mTabCount){
			return;
		}
		if(mCurrentTabIndex != tabIndex){
			int oldTab = mCurrentTabIndex;
			getChildTabViewAt(mCurrentTabIndex).setSelected(false);
			mCurrentTabIndex = tabIndex;
			getChildTabViewAt(mCurrentTabIndex).setSelected(true);
			doAnimation(oldTab, mCurrentTabIndex);
		}else{
			if(!getChildTabViewAt(mCurrentTabIndex).isSelected()){
				getChildTabViewAt(mCurrentTabIndex).setSelected(true);
			}
		}
	}
	/**
	 * 进行tab切换时的动画
	 * @param oldTab	切换前的tab
	 * @param newTab	切换后的tab
	 */
	private void doAnimation(int oldTab, int newTab){
		if(mBackgroundView != null){
			
			float distanceX = 0;
			long currentTime = AnimationUtils.currentAnimationTimeMillis();
			if(mAnimationInterpolatedTime != 1.0f && mTranslateAnimation != null){
				// 计算出当前的位置				
				Transformation transformation = new Transformation();
				boolean bRunning = mTranslateAnimation.getTransformation(currentTime, transformation);
				if(bRunning){
					float[] values = new float[9];
					transformation.getMatrix().getValues(values);
					
					// 获取当前的位置偏移
					distanceX = values[Matrix.MTRANS_X];
					//Log.e("" + bRunning, "" + distanceX);
				}
//				long startInterval = currentTime - mTranslateAnimation.getStartTime();
				// 重置状态
				mAnimationInterpolatedTime = 1.0f;
			}
			
			initBackgroundPosition(newTab);
			
			// 计算出原来需要走的距离
			float oldDistance = mTabWidth * (oldTab - newTab);
			// 现在需要走的距离
			float newDistance = mTabWidth * (oldTab - newTab) + distanceX;
			mTranslateAnimation = new MyTranslateAnimation(newDistance, 0, 0, 0);
			mTranslateAnimation.setInterpolator(mContext, android.R.anim.accelerate_decelerate_interpolator);
			
			oldDistance = Math.abs(oldDistance);
			newDistance = Math.abs(newDistance);
			// 计算出需要再移动的时间
			long durationTime = (long) (ANIMATION_TIME * (1 - (oldDistance - newDistance)/((oldDistance > newDistance) ? oldDistance : newDistance)));
//			if(DEBUG){
//				Log.e(TAG, "current duration time:" + durationTime);
//			}
			mTranslateAnimation.setDuration(durationTime);
			// 这里是使用线程刷新控件，否则动画过程中会有残影
			if(mThreadInvalidate != null && mThreadInvalidate.isAlive()){
				mThreadInvalidate.interrupt();
				mThreadInvalidate = null;
			}
			mThreadInvalidate = new Thread(new Runnable() {
				public void run() {
					final int POST_DELAY = 20;
					int count = 0;
					while(!Thread.interrupted() && count < ANIMATION_TIME){
						MyTabWidget.this.postInvalidate();
						try {
							Thread.sleep(POST_DELAY);
						} catch (InterruptedException e) {
							return;
						}
						count += POST_DELAY;
					}
					
				}
			});
			mTranslateAnimation.setAnimationListener(new Animation.AnimationListener() {			
				public void onAnimationStart(Animation animation) {
					if(mThreadInvalidate != null){
						mThreadInvalidate.start();
					}
				}
				
				public void onAnimationRepeat(Animation animation) {
				}
				
				public void onAnimationEnd(Animation animation) {
					if(mThreadInvalidate != null){
						mThreadInvalidate.interrupt();
					}
					
				}
			});
			
			if(B_USE_ALPHA){
				// 使用透明
				
				AnimationSet animationSet = new AnimationSet(true);
				animationSet.setInterpolator(mContext, android.R.anim.accelerate_decelerate_interpolator);
				animationSet.setFillEnabled(false);
				animationSet.addAnimation(mTranslateAnimation);
				
				float oldAlpha = -1;
				if(durationTime != ANIMATION_TIME){
					// 需要获取当前的alpha值
					Transformation transformation = new Transformation();
					if(mAlphaAnimation1 != null && mAlphaAnimation1.getTransformation(currentTime, transformation)){
						oldAlpha = transformation.getAlpha();
					}else{
						if(mAlphaAnimation2 != null && mAlphaAnimation2.getTransformation(currentTime, transformation)){
							oldAlpha = transformation.getAlpha();
						}
					}
				}
				if(oldAlpha == -1 || oldAlpha < ALPHA_VALUE){
					// 不需要处理
					mAlphaAnimation1 = new MyAlphaAnimation(1.0f, ALPHA_VALUE);
					mAlphaAnimation1.setDuration(durationTime / 2);
					mAlphaAnimation1.setFillEnabled(true);
					mAlphaAnimation1.setFillBefore(true);
					mAlphaAnimation1.setFillAfter(false);
					animationSet.addAnimation(mAlphaAnimation1);
					
					mAlphaAnimation2 = new MyAlphaAnimation(ALPHA_VALUE, 1.0f);
					mAlphaAnimation2.setStartOffset(durationTime / 2);
					mAlphaAnimation2.setDuration(durationTime / 2);
					mAlphaAnimation2.setFillEnabled(true);
					mAlphaAnimation2.setFillBefore(false);
					mAlphaAnimation2.setFillAfter(true);
					animationSet.addAnimation(mAlphaAnimation2);
				}else{
					if( durationTime * 2 < ANIMATION_TIME){
						// 只需要设置一个alpha效果
						mAlphaAnimation1 = null;
						
						mAlphaAnimation2 = new MyAlphaAnimation(oldAlpha, 1.0f);
						mAlphaAnimation2.setDuration(durationTime);
						mAlphaAnimation2.setFillEnabled(true);
						mAlphaAnimation2.setFillAfter(true);
						mAlphaAnimation2.setFillBefore(false);
						animationSet.addAnimation(mAlphaAnimation2);
					}else{
						// 严格来说，这里需要计算每个alpha的比例时间
						mAlphaAnimation1 = new MyAlphaAnimation(oldAlpha, ALPHA_VALUE);
						mAlphaAnimation1.setDuration(durationTime / 2);	
						mAlphaAnimation1.setFillEnabled(true);
						mAlphaAnimation1.setFillBefore(true);
						mAlphaAnimation1.setFillAfter(false);
						animationSet.addAnimation(mAlphaAnimation1);
						
						mAlphaAnimation2 = new MyAlphaAnimation(ALPHA_VALUE, 1.0f);
						mAlphaAnimation2.setStartOffset(durationTime / 2);
						mAlphaAnimation2.setDuration(durationTime / 2);
						mAlphaAnimation2.setFillEnabled(true);
						mAlphaAnimation2.setFillAfter(true);
						mAlphaAnimation2.setFillBefore(false);
						animationSet.addAnimation(mAlphaAnimation2);
					}
				}
				
				mBackgroundView.startAnimation(animationSet);
			}else{
				mBackgroundView.startAnimation(mTranslateAnimation);
			}
		}
	}
	/**
	 * Sets the current tab and focuses the UI on it. This method makes sure that the focused tab matches the selected
	 * tab, normally at {@link #setCurrentTab}. Normally this would not be an issue if we go through the UI, since the
	 * UI is responsible for calling TabWidget.onFocusChanged(), but in the case where we are selecting the tab
	 * programmatically, we'll need to make sure focus keeps up.
	 * 
	 * @param index
	 *            The tab that you want focused (highlighted in orange) and selected (tab brought to the front of the
	 *            widget)
	 * 
	 * @see #setCurrentTab
	 */
	public void focusCurrentTab(int index) {
		final int oldTab = mCurrentTabIndex;

		// set the tab
		setCurrentTab(index);

		// change the focus if applicable.
		if (oldTab != index) {
			getChildTabViewAt(index).requestFocus();
		}
	}
	
	public void setEnabled(boolean bEnable){
		super.setEnabled(bEnable);
	}
	
	@Override
	public void addView(View child) {
		// 必须使用LinearLayout的布局参数
//		if(child.getLayoutParams() == null){
			final LinearLayout.LayoutParams lp = new LayoutParams(0, ViewGroup.LayoutParams.FILL_PARENT, 1.0f);
			lp.setMargins(0, 0, 0, 0);
			child.setLayoutParams(lp);
//		}
		child.setFocusable(true);
		child.setClickable(true);
		super.addView(child);
		child.setOnClickListener(new TabClickListener(mTabCount++));
	}
	
	
	private class TabClickListener implements View.OnClickListener{
		private final int mIndex;
		public TabClickListener(int index){
			mIndex = index;
		}
		public void onClick(View v) {
			if(mSelectionChangeListener != null){
				// 点击事件由tabhost相应，由host决定是否切换tab
				mSelectionChangeListener.onTabSelectionChanged(mIndex);
			}
		}
		
	}
	
	@Override
	protected void dispatchDraw(Canvas canvas) {
		super.dispatchDraw(canvas);
	}
	@Override
	public void childDrawableStateChanged(View child) {
		if (child == getChildTabViewAt(mCurrentTabIndex)) {
			invalidate();
		}
		super.childDrawableStateChanged(child);
	}

	public void setTabSelectionListener(OnTabSelectionChanged listener){
		mSelectionChangeListener = listener;
	}
	private OnTabSelectionChanged mSelectionChangeListener;

	interface OnTabSelectionChanged{
		void onTabSelectionChanged(int tabIndex);
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
		// 计算出layout中tab的大小和位置
		mLayoutWidth = r - l;
		mTabWidth = mLayoutWidth / mTabCount;
		initBackgroundPosition(mCurrentTabIndex);
	}
	/**
	 * 设置用于动画的view,暂时只有{@link MyAnimTabWidget}能调用该方法
	 * @param view 需要执行动画的view
	 */
	public void setBackgroundView(ImageView view){
		mBackgroundView = view;
	}
	private void initBackgroundPosition(int positon){
		if(mBackgroundView != null){
			mBackgroundView.clearAnimation();
			int margin = positon * mTabWidth;
			RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(mTabWidth, RelativeLayout.LayoutParams.FILL_PARENT);
			lp.setMargins(margin, 0, 0, 0);
			mBackgroundView.setLayoutParams(lp);
			mBackgroundView.invalidate();
		}
	}
	void setTabWidgetAnimBackground(int resource){
		// 不需要处理
	}
	
	private final class MyTranslateAnimation extends TranslateAnimation{

		public MyTranslateAnimation(float fromXDelta, float toXDelta,
				float fromYDelta, float toYDelta) {
			super(fromXDelta, toXDelta, fromYDelta, toYDelta);
		}

		@Override
		protected void applyTransformation(float interpolatedTime,
				Transformation t) {
			// 记录移动的状态
			super.applyTransformation(interpolatedTime, t);
			mAnimationInterpolatedTime = interpolatedTime;
		}
		
	}
	
	private final class MyAlphaAnimation extends AlphaAnimation{
		private long mTime = 0;
		public MyAlphaAnimation(float fromAlpha, float toAlpha) {
			super(fromAlpha, toAlpha);
		}
		@Override
		protected void applyTransformation(float interpolatedTime,
				Transformation t) {
			
			// 需要过滤掉第一次getStartOffset > 0的alpha转换
			// 因为即使设置了fillAfter为false，在刚开始时，仍然会进行一次初始化的转换
			if(interpolatedTime == 0 && getStartOffset() > 0){
				return;
			}
			super.applyTransformation(interpolatedTime, t);
			if(System.currentTimeMillis() - mTime > 100){
				mTime = System.currentTimeMillis();
				//Log.e("alpha" + mId, "" + t.getAlpha());
			}
		}
		
	}
}
